import json
import os
from multiprocessing import Process

from lxml import etree

from util.Logger import Logger
from util.selenium.webdriver.common.by import By

from base.BaseMethod import BM
from util.DataQuery.FormDataQuery import FormDataQuery
from util.DataQuery.hzflowOperation import hzflowOperation

from settings import MultiRecordList, web_type, class_to_tablename, log_path
from util.g import g
from util.inform.sendEmail import sendEmail
from util.redis_manage_file import redisManageFile


def quit(class_obj):
    class_obj.driver.quit()
    hzflowOperation.update_host_process(obj=hzflowOperation.get_log(co_id=g.co_id, year=g.year), mark_info="")
    os._exit(0)


def FormDataDecorator(func):
    def wrapper(*args, **kwargs):
        if not args:
            raise Exception('this func is not class method. --custom-- in FormDataDecorator')

        class_obj = args[0]
        class_name = class_obj.__class__.__name__
        if class_name == 'LoginPage':
            # 如果是登录页面直接返回
            return func(*args)
        query_obj = FormDataQuery(class_name=class_name)
        # 查看撤回状态 撤回次数不一致则停止上传并退出
        is_revert = query_obj.check_revert()
        if is_revert is True:
            hzflowOperation.tran_to_data(co_id=g.co_id, year=g.year, status=5)
            class_obj.driver.quit()
            os._exit(0)

        # # # 获取函数的参数列表
        func_param_list = list(func.__code__.co_varnames)
        # # # 删除参数列表的第一个元素。 类中的方法第一个元素为 self -- 即对象本身。 这里的 func_param_list 中元素类型都为字符串类型
        func_param_list.pop(0)
        query_obj.func_param_list = func_param_list

        # # # 这里修改一下 ， 该函数获取到的数据为 字典类型 判断 在 MultiRecordList 中的 数据保留 ID 其余正常
        result = query_obj.func_data()

        record_var = "{}Data".format(class_name)
        setattr(g, "current_class", class_name)
        if class_name == "WriteRegistrationForm" or class_name == "WriteMaincaseForm":
            setattr(g, "{}Result".format(class_name), result)

        if class_name == "IAStaDesc":
            sort_num_li = [sta.get("sort_num") for sta in result]
            flag = BM.check_lenth(sort_num_li)
            if not flag:
                msg = "{} {} 排序号重复, 请手动修改".format(
                    g.status.get("entname"), class_to_tablename.get(class_name))
                a = sendEmail(subject="autoflow_{}_{}".format(web_type, g.co_id), content=msg)
                a.content = msg
                a.send_mail()
                return wrapper
                # sort_num,sta_name,sta_type,trans_ids,trans_result,ipr_ids,ipr_num,tech_statype,sta_material,sta_desc
        # 当查询到的记录数小于 等于0 时 直接 置状态为1 并返回
        if len(result) <= 0:
            hzflowOperation().commonModel(class_name=class_name, value=1)
            return wrapper
        g.logger.info("get data and upload: {}".format(class_name))
        data_li = []
        for index, i in enumerate(result, 1):
            setattr(g, record_var, i)
            # g.logger.info("set g.{} = {}".format(record_var, i))
            if class_name in MultiRecordList:
                if "id" not in func_param_list:
                    g.ts_id = i.pop('id')
                else:
                    g.ts_id = i.get("id")
                g.logger.info("{}-----id: {}".format(class_name, g.ts_id))
            else:
                _ = i.pop('id') if 'id' in i else None
            # # param_list 需要在 for 循环中赋值，否则 param_list 中的参数会一直增加
            param_list = [class_obj, ]
            g.logger.info("{}: {}".format(class_name, i))
            res = None
            try:
                res = func(class_obj, **i)
                # 单条数据页面会返回 true 或 false 来表示是否上传成功
                if res and type(res) != bool:
                    data_li.append(res)
            # except Exception as err:
            except TimeoutError as err:
                #  这里需要判断 class_name 是否在 MultiRecordList 中， 如果在 需要处理 id 如果不在
                # 就更新 ent_flow_data 进度表 中的状态值 为 -1
                # 然后在 ent_error_info 中创建一条记录， 将 错误信息记录在 表中
                # 处理 id 需要最后处理完之后 在 ent_records_status 中创建一条记录 记录 录入成功和录入失败的
                # 数据条数 和 id
                # print(err)
                # TODO 发邮件通知 材料上传错误
                li = list()
                li.extend(param_list)
                li.append(i)
                # g.logger.error("信息录入错误: {} data: {}".format(err, li))
                err_msg = "信息录入错误: {} file: {} lines: {} data: {}".format(err,
                                                                          err.__traceback__.tb_frame.f_globals[
                                                                              "__file__"],
                                                                          err.__traceback__.tb_lineno, li)
                g.logger.error(err_msg)
                sendEmail(subject="autoflow", content=err_msg)
                if class_name in MultiRecordList:
                    g.error_list.append(str(g.ts_id))
                else:
                    hzflowOperation().commonExceptionModel(class_name=class_name, err=err)

                # TODO 退出当前材料上传 开始下一家
                quit(class_obj=class_obj)
            else:
                if res is not None and isinstance(res, bool):
                    if res:
                        hzflowOperation().commonModel(class_name=class_name, value=1)
                    else:
                        hzflowOperation().commonModel(class_name=class_name, value=-1)
            if g.is_continue:
                g.is_continue = False
                continue
        if data_li:
            return data_li

        # # # # # # TODO 这里需要处理 MultiRecordList 中的 模块错误
        if class_name in MultiRecordList:
            if class_name == "WriteRdcostForm":
                record_data_var = "{}Record".format(class_name)
                record_data = getattr(g, record_data_var)
            else:
                record_data = getattr(g, class_name)

            g.logger.info("{} 已填写数量:{} 数据库数量:{}".format(class_name, len(record_data), len(result)))
            if len(record_data) != len(result):
                hzflowOperation().commonModel(class_name=class_name, value=-2)
                if class_name in ["WriteIpForm", "WriteRDForm", "WritePSForm"]:
                    class_obj.driver.quit()
                    hzflowOperation.update_host_process_by_co_id(co_id=g.co_id, year=g.year, host_process="")
                    os._exit(0)
                return wrapper
            hzflowOperation().recordsModel(error_ids=g.error_list, completed_ids=g.completed_list,
                                           class_name=class_name)

    return wrapper


def CheckProcess(func):
    def wrapper(*args, **kwargs):
        class_obj = args[0]
        class_name = class_obj.__class__.__name__
        res = None
        try:
            res = func(*args)
        except Exception as err:
            g.logger.error("附件上传出错: err={}".format(err))
            # TODO 发邮件通知 材料上传错误
            hzflowOperation.changeLog(class_name=class_name, value=-1)

            quit(class_obj=class_obj)
        else:
            if res is not None:
                if res is True:
                    hzflowOperation.changeLog(class_name=class_name, value=1)
                    return wrapper
                if res is False:
                    hzflowOperation.changeLog(class_name=class_name, value=-1)
                    return wrapper
            hzflowOperation.changeLog(class_name=class_name, value=1)
    return wrapper


# # # 测试 FormDataDecorator 使用的 class 。
class WriteStandForm():
    @FormDataDecorator
    def write_stand_form(self, stand_name='建筑幕墙工程BIM实施标准', stand_num='T/CBDA7-2016', stand_level='行业', stand_way='参与'):
        print(f'stand_name: {stand_name}\nstand_num: {stand_num}\nstand_level: {stand_level}\nstand_way: {stand_way}')


class WriteInnovationAbilityForm():
    @FormDataDecorator
    def write_innovation_ability_form(self, ripr_iec='-------------', sta_desc='______________________',
                                      rdm_desc='+++++++++++', mgt_tech='================='):
        print(f' ripr_iec: {ripr_iec}\n sta_desc: {sta_desc}\n rdm_desc: {rdm_desc}\n mgt_tech: {mgt_tech}')
        pass


class IAStaDesc():
    @FormDataDecorator
    def ia_sta_desc(self, id='', sta_name='test', sta_type='专利', sta_source='自主研发', trans_result='新产品',
                    trans_date='2011', sort_num=0, ipr_ids='0,1,3', rd_ids='0', ps_ids='0', trans_ids=''):
        print(
            f'id: {id}\nsta_name: {sta_name}\nsta_type: {sta_type}\nsta_source: {sta_source}\ntrans_result: {trans_result}\ntrans_date: {trans_date}\nsort_num: {sort_num}\nipr_ids: {ipr_ids}\nrd_ids: {rd_ids}\nps_ids: {ps_ids}\ntrans_ids: {trans_ids}')


class WriteRegistrationForm():
    @FormDataDecorator
    def write_registration_form(self, contact='', contact_phone='', contact_tel='', contact_fax='', contact_email='',
                                legal_phone='', legal_tel='', legal_fax='', legal_email='', dom='', postalcode='',
                                scale='', hitech_field_namelist='', gopublic="", stockcat='', gopublictime='',
                                stockcode='', opscope='；', entbrief_intro=''):
        a = [contact, contact_phone, contact_tel, contact_fax, contact_email, legal_phone, legal_tel, legal_fax,
             legal_email, dom, postalcode, scale, hitech_field_namelist, gopublic, stockcat, gopublictime, stockcode,
             opscope, entbrief_intro]
        a = [str(i) for i in a]
        print("\n".join(a))
        print("scale: ", scale)


class WriteApplicationCover():
    # @FormDataDecorator
    def __call__(self, *args, **kwargs):
        print("use __call__ as {}".format(self.__class__.__name__))

    def __init__(self, driver):
        self.driver = driver

    @FormDataDecorator
    def main(self, cert_org='北京市认定机构办公室', app_date='2019-12-12'):
        a = [str(cert_org), str(app_date)]
        print("\n".join(a))


if __name__ == '__main__':
    # WriteRegistrationForm().write_registration_form()
    #
    # WriteApplicationCover().write_application_cover()
    #
    # class therad(threading.Thread):
    #     def __init__(self, func):
    #         super(therad, self).__init__()
    #
    #     def run(self):
    #
    #         pass
    g.logger = Logger(log_file_name=log_path.replace("log.txt", "autoflow_pdfSplit.log"), log_level=Logger.DEBUG,
                      logger_name="autoflow_pdfSplit").get_log()
    g.co_id = 119055
    g.year = 2021
    page = WriteRegistrationForm()
    page.write_registration_form()
    # page = globals()["WriteApplicationCover"](driver="a")
    # page.main()
    # print(page.__call__)

    pass

    # a = WriteStandForm()
    # a.write_stand_form()
    # b = WriteInnovationAbilityForm()
    # b.write_innovation_ability_form()
    # c = WriteStandForm()
    # c.write_stand_form()

    # d = IAStaDesc()
    # d.ia_sta_desc()
